package com.javaweb.interceptor;

import java.lang.reflect.Method;
import java.time.Duration;
import java.util.List;

import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import com.javaweb.annotation.url.ControllerMethod;
import com.javaweb.base.BaseConfigMemory;
import com.javaweb.base.BaseInject;
import com.javaweb.base.po.Interfaces;
import com.javaweb.constant.SystemConstant;
import com.javaweb.enums.AuthEnum;
import com.javaweb.util.core.StringUtil;
import com.javaweb.web.eo.TokenData;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

/**
 * 权限拦截器
 * @see com.javaweb.config.webmvc.WebMvcConfig#addInterceptors
 * @author tank2140896
 */
@Component
public class WebPermissionInterceptor implements HandlerInterceptor {
	
	/**
	 * 预处理（本方法异常不应该主动抛出）
	 */
	public boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler) throws Exception {
		//放行所有OPTIONS请求
		if(SystemConstant.HTTP_REQUEST_METHOD_OPTIONS.equalsIgnoreCase(request.getMethod())) {
            return true;
        }
		//获取ControllerMethod注解中的AuthEnum
		AuthEnum authEnum = getUrlPermission(handler);
		//如果是无需登录访问（任何人都能访问），则直接放行
		if(AuthEnum.NO_LOGIN==authEnum) {
			return true;
		}
		//校验登录访问权限，最基本要素就是要携带token
		TokenData tokenData = BaseInject.getTokenData(BaseInject.getToken(request)); 
		if((tokenData==null)||(tokenData.getUser()==null)||(StringUtil.isEmpty(tokenData.getUser().getUserId()))) {
			request.getRequestDispatcher("/invalidRequest").forward(request,response);
			return false;
		}
		//携带token后还要校验token是否有效
		Duration duration = Duration.ofMinutes(BaseConfigMemory.redistokenExpireMinutes);
		String key = BaseInject.getRedisTokenKey(tokenData);
		if(AuthEnum.LOGIN==authEnum){
			BaseInject.staticSetDataToRedis(key,tokenData,duration);
			return true;
		}
		//String classMethod = ((HandlerMethod)handler).getBeanType().getName() + CommonConstant.POUND + handlerMethod.getMethod().getName();
		//classMethod.equals(interfaces.getClassMethod()
		//判断请求接口URL是否存在
		Interfaces interfaces = (Interfaces)request.getAttribute(SystemConstant.REQUEST_URL_CHAIN_ATTRIBUTE_NAME);
		if(interfaces==null||StringUtil.isEmpty(interfaces.getUrl())) {
			request.getRequestDispatcher("/noAuthory").forward(request,response);
			return false;
		}
		//判断是否授权
		String url = interfaces.getUrl();//获得接口URL通配
		List<String> apiUrlList = tokenData.getApiUrlList();//后端接口列表
		if(apiUrlList.contains(url)) {//等价于equals
			BaseInject.staticSetDataToRedis(key,tokenData,duration);
			return true;
		} else {
			request.getRequestDispatcher("/noAuthory").forward(request,response);
			return false;
		}
	}
	
	/**
	 * 获取接口上的@ControllerMethod注解
	 * @param handler handler
	 * @return AuthEnum 权限枚举
	 */
	private AuthEnum getUrlPermission(Object handler) {
	    if(handler instanceof HandlerMethod handlerMethod) {
            Method method = handlerMethod.getMethod();
            //AnnotatedElementUtils.isAnnotated(method,ControllerMethod.class);
            ControllerMethod controllerMethod = method.getAnnotation(ControllerMethod.class);
            return controllerMethod==null ? AuthEnum.NO_LOGIN : controllerMethod.auth();
        }
	    return AuthEnum.PERMISSION;
	}
	
}
